using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Collections;

using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Net.Sockets;
using BrainTechLLC.ThreadSafeObjects;
using BrainTechLLC;

namespace Mud.EmlenMudMain
{
#if NO_SILVERLIGHT
    [Serializable]
#endif
    public class Stats : IStats
    {
        private int[] rgStats = new int[10];

        public int[] RgStats
        {
            get { return rgStats; }
            set { rgStats = value; }
        }

        public int this[StatTypes st]
        {
            get
            {
                return rgStats[(int)st];
            }
            set
            {
                rgStats[(int)st] = value;
            }
        }
        public int this[int st]
        {
            get
            {
                return rgStats[st];
            }
            set
            {
                rgStats[st] = value;
            }
        }
    }

#if NO_SILVERLIGHT
    [Serializable]
#endif
    public class PlayerData
    {
        public void ToGameChar(GameChar chr)
        {
            chr.AddOrSetProperty("VnumRoomBeforeArena", vnumRoomBeforeArena);
            chr.AddOrSetProperty("VnumRoomBeforeBattleground", vnumRoomBeforeBattleground);
            chr.AddOrSetProperty("TimerAFK", timerAFK);
            chr.AddOrSetProperty("Title", this.Title);
            chr.AddOrSetProperty("SpecialBits", this.Specialbits);
            chr.Name.ShortDescription = this.short_descr;
            chr.AddOrSetProperty("ShowLevel", this.show_lev);
            chr.AddOrSetProperty("Sex", this.sex);
            chr.AddOrSetProperty("TempRoom", this.temp_room);
            chr.AddOrSetProperty("TickCounts", this.tickcounts);
            chr.AddOrSetProperty("TravelPoints", this.tps);
            chr.AddOrSetProperty("Prompt", this.Prompt);
            chr.AddOrSetProperty("Bounty", this.Bounty);
            chr.AddOrSetProperty("BeamIn", this.beamin);
            chr.AddOrSetProperty("BeamOut", this.beamout);
            chr.AddOrSetProperty("Security", this.Security);
            chr.AddOrSetProperty("WizInvis", this.Wizinvis);
            chr.AddOrSetProperty("Warpoints", this.Warpoints);
            chr.AddOrSetProperty("Warned", this.warned);
            chr.AddOrSetProperty("VotingOn", this.Voting_on);
            chr.AddOrSetProperty("TotalKills", this.Totalkills);
            chr.AddOrSetProperty("ResistSummon", this.Resist_summon);
            chr.AddOrSetProperty("SavingThrow", this.saving_throw);
            chr.AddOrSetProperty("Quiet", this.Quiet);
            chr.AddOrSetProperty("RaceName", this.Racename);
            chr.AddOrSetProperty("QuestFlag", this.Questflag);
            chr.AddOrSetProperty("PrayPoints", this.Pray_points);
            chr.AddOrSetProperty("Professions", this.Professions);
            chr.AddOrSetProperty("PracticePoints", this.Practice);
            chr.AddOrSetProperty("PlusSneak", this.Plus_sneak);
            chr.AddOrSetProperty("PlusKick", this.Plus_kick);
            chr.AddOrSetProperty("PlusHide", this.plus_hide);
            chr.AddOrSetProperty("PlayTime", this.Played);
            chr.AddOrSetProperty("RemortTimes", this.NRemortTimes);
            chr.AddOrSetProperty("NoQuitPK", this.No_quit_pk);
            chr.AddOrSetProperty("NoSpam", this.No_spam);
            chr.AddOrSetProperty("NoQuit", this.No_quit);
            chr.AddOrSetProperty("NewExperience", this.New_exp);
            chr.AddOrSetProperty("NaturalArmor", this.Nat_armor);
            chr.AddOrSetProperty("NaturalAbilities", this.Nat_abilities);
            chr.AddOrSetProperty("MaxMana", this.n_max_mana);
            chr.AddOrSetProperty("Mana", this.n_mana);
            chr.Name.Description = this.long_descr;
            chr.AddOrSetProperty("LogonTime", this.logon);
            chr.AddOrSetProperty("ListenAuction", this.listen_auction);
            chr.AddOrSetProperty("Level", this.level);
            chr.AddOrSetProperty("LearningPoints", this.learn);
            chr.AddOrSetProperty("LastNoteDate", this.last_note);
            chr.AddOrSetProperty("KillPoints", this.killpoints);
            chr.AddOrSetProperty("JustInvestigated", this.just_investigated);
            chr.AddOrSetProperty("JailServed", this.jail_served);
            chr.AddOrSetProperty("Implants1", this.implants_1);
            chr.AddOrSetProperty("Implants2", this.implants_2);
            chr.AddOrSetProperty("Guilds", this.guilds);
            chr.AddOrSetProperty("ExtraSkills", this.extraskills);
            chr.AddOrSetProperty("Effects1", this.effects1);
            chr.AddOrSetProperty("Deaths", this.deaths);
            chr.AddOrSetProperty("Deaf", this.deaf);
            chr.AddOrSetProperty("IgnoreChannels", this.chan_ignore);
            chr.AddOrSetProperty("ChallengedBy", this.challenged_by);
            chr.AddOrSetProperty("Challenged", this.challenged);
            chr.AddOrSetProperty("ChallengeTime", this.challenge_time);
            chr.AddOrSetProperty("ChallengeOn", this.challenge_on);
            chr.AddOrSetProperty("CarryWeight", this.carry_weight);
            chr.AddOrSetProperty("CarryNumber", this.carry_number);
            chr.AddOrSetProperty("BGF", this.bgf);
            chr.AddOrSetProperty("ArenaMessage", this.arena_msg);
            chr.AddOrSetProperty("InBank", this.bank);
            chr.AddOrSetProperty("Alignment", this.alignment);
        }

        public PlayerData() { }
        public const int MAXST = 30;	/* How many items can a person have in person rgObjectsStored? */

        private int vnumRoomBeforeArena = 0;				/* Was in currentRoom before arena */

        public int VnumRoomBeforeArena
        {
            get { return vnumRoomBeforeArena; }
            set { vnumRoomBeforeArena = value; }
        }
        private int vnumRoomBeforeBattleground = 0;	/* Was in this currentRoom before battleground */

        public int VnumRoomBeforeBattleground
        {
            get { return vnumRoomBeforeBattleground; }
            set { vnumRoomBeforeBattleground = value; }
        }
        private int timerAFK = 0;

        public int TimerAFK
        {
            get { return timerAFK; }
            set { timerAFK = value; }
        }

        private string pwd = "";			/* Password */

        public string Pwd
        {
            get { return pwd; }
            set { pwd = value; }
        }
        private string rpwd = "";			/* Internal use */

        public string Rpwd
        {
            get { return rpwd; }
            set { rpwd = value; }
        }
        private string title = "";		/* Character's title */

        public string Title
        {
            get { return title; }
            set { title = value; }
        }
        private List<ObjectData> storage = new List<ObjectData>(); /* Storage objects in the bank */

        public List<ObjectData> Storage
        {
            get { return storage; }
            set { storage = value; }
        }
        private PlayerSpecialBits specialbits = PlayerSpecialBits.NONE;

        public PlayerSpecialBits Specialbits
        {
            get { return specialbits; }
            set { specialbits = value; }
        }
        private int bounty;		/* bounty.. UNUSED */

        public int Bounty
        {
            get { return bounty; }
            set { bounty = value; }
        }
        private int prompt;		/* prompt selection string /
		public string rprompt;		/* Real string prompt */


        public int Prompt
        {
            get { return prompt; }
            set { prompt = value; }
        }
        private Dictionary<long, int> ignore = new Dictionary<long, int>(); /* Ignored character list */

        public Dictionary<long, int> Ignore
        {
            get { return ignore; }
            set { ignore = value; }
        }
        private string beamin = "";		/* Beam in message (immorts) */

        public string Beamin
        {
            get { return beamin; }
            set { beamin = value; }
        }
        private string beamout = "";		/* Beam out message (immorts) */

        public string Beamout
        {
            get { return beamout; }
            set { beamout = value; }
        }
        private string oldgrep = "";		/* Last grep'd command (immorts) */

        public string Oldgrep
        {
            get { return oldgrep; }
            set { oldgrep = value; }
        }
        private int security = 0;		/* Security level.. UNUSED */

        public int Security
        {
            get { return security; }
            set { security = value; }
        }
        private int wizinvis = 0;		/* WizInvis level */

        public int Wizinvis
        {
            get { return wizinvis; }
            set { wizinvis = value; }
        }
        private ChannelTypes deaf;			/* Deaf to these channels */

        public ChannelTypes Deaf
        {
            get { return deaf; }
            set { deaf = value; }
        }
        private int chan_ignore;		/* Deaf to these new style channels */

        public int Chan_ignore
        {
            get { return chan_ignore; }
            set { chan_ignore = value; }
        }
        private string[] chan_color = new string[10];	/* Channel colors */

        public string[] Chan_color
        {
            get { return chan_color; }
            set { chan_color = value; }
        }
        private int pray_points;		/* Pray points, unused. */

        public int Pray_points
        {
            get { return pray_points; }
            set { pray_points = value; }
        }

        private long played;		/* Second played */

        public long Played
        {
            get { return played; }
            set { played = value; }
        }
        private Professions professions;	/* Profession flags */

        public Professions Professions
        {
            get { return professions; }
            set { professions = value; }
        }
        private int n_mana = 0;		/* Natural mana */

        public int N_mana
        {
            get { return n_mana; }
            set { n_mana = value; }
        }
        private int n_max_mana = 0;		/* Natural Max mana */

        public int N_max_mana
        {
            get { return n_max_mana; }
            set { n_max_mana = value; }
        }
        private int saving_throw = 0;		/* Saving throw for spells */

        public int Saving_throw
        {
            get { return saving_throw; }
            set { saving_throw = value; }
        }
        private ExtraSkills extraskills = ExtraSkills.NONE;		/* Cool extra skills/abilities */

        public ExtraSkills Extraskills
        {
            get { return extraskills; }
            set { extraskills = value; }
        }
        private Dictionary<long, int> killed_mobs = new Dictionary<long, int>(); /* Mob trophies */

        public Dictionary<long, int> Killed_mobs
        {
            get { return killed_mobs; }
            set { killed_mobs = value; }
        }
        private int resist_summon = 0;	/* Resistance to summon value */

        public int Resist_summon
        {
            get { return resist_summon; }
            set { resist_summon = value; }
        }
        private int plus_kick = 0;	/* Extra kick bonus value */

        public int Plus_kick
        {
            get { return plus_kick; }
            set { plus_kick = value; }
        }
        private int plus_sneak = 0;	/* Extra sneak bonus value */

        public int Plus_sneak
        {
            get { return plus_sneak; }
            set { plus_sneak = value; }
        }
        private int plus_hide = 0;	/* Extra hide bonus value */

        public int Plus_hide
        {
            get { return plus_hide; }
            set { plus_hide = value; }
        }
        private int transport_quest = 0;	/* Unused!!  Used internally */

        public int Transport_quest
        {
            get { return transport_quest; }
            set { transport_quest = value; }
        }
        private bool listen_auction = false;	/* Listening to the current auction bidding? */

        public bool Listen_auction
        {
            get { return listen_auction; }
            set { listen_auction = value; }
        }
        private int[] colors = new int[32];	/* Colors for old style channels */

        public int[] Colors
        {
            get { return colors; }
            set { colors = value; }
        }
        private int practice = 0;		/* Practice sessions left. */

        public int Practice
        {
            get { return practice; }
            set { practice = value; }
        }
        private int learn = 0;		/* Learn points left. */

        public int Learn
        {
            get { return learn; }
            set { learn = value; }
        }
        private bool new_exp = false;		/* New experience format?  Internal use */

        public bool New_exp
        {
            get { return new_exp; }
            set { new_exp = value; }
        }
        private int voting_on = 0;		/* Unused.. internal use */

        public int Voting_on
        {
            get { return voting_on; }
            set { voting_on = value; }
        }
        private int nat_armor = 0;		/* Natural naturalArmor class for skin */

        public int Nat_armor
        {
            get { return nat_armor; }
            set { nat_armor = value; }
        }
        private int nat_abilities = 0;		/* Natural abilities */

        public int Nat_abilities
        {
            get { return nat_abilities; }
            set { nat_abilities = value; }
        }
        private DateTime logon;		/* Logon time */

        public DateTime Logon
        {
            get { return logon; }
            set { logon = value; }
        }
        private DateTime last_note;		/* Last note read date-time stamp */

        public DateTime Last_note
        {
            get { return last_note; }
            set { last_note = value; }
        }
        private int[] convo = new int[256];		/* Convo 199 is cur cursor pos */

        public int[] Convo
        {
            get { return convo; }
            set { convo = value; }
        }
        //[NonSerialized]
        //public ArrayList pets = new ArrayList(0);

        //public ArrayList Pets
        //{
        //    get { return pets; }
        //    set { pets = value; }
        //}
        //[NonSerialized]
        //public ArrayList pet_move = new ArrayList(0);		/* Pets' MPCurrent points */

        //public ArrayList Pet_move
        //{
        //    get { return pet_move; }
        //    set { pet_move = value; }
        //}
        //[NonSerialized]
        //public ArrayList pet_hps = new ArrayList(0);		/* Pets' HPCurrent points */

        //public ArrayList Pet_hps
        //{
        //    get { return pet_hps; }
        //    set { pet_hps = value; }
        //}
        //[NonSerialized]
        //public ArrayList pet_temp = new ArrayList(0); /* Pet's temp values */

        //public ArrayList Pet_temp
        //{
        //    get { return pet_temp; }
        //    set { pet_temp = value; }
        //}

        //private Hashtable temp_flag = new Hashtable(8);	/* Temp flags for OLD quest method */

        //public Hashtable Temp_flag
        //{
        //    get { return temp_flag; }
        //    set { temp_flag = value; }
        //}
        //private Hashtable in_progress = new Hashtable(8);	/* Temp flags for OLD quest method */

        //public Hashtable In_progress
        //{
        //    get { return in_progress; }
        //    set { in_progress = value; }
        //}
        //private Hashtable complete = new Hashtable(8); /* Temp flags for OLD quest method */

        //public Hashtable Complete
        //{
        //    get { return complete; }
        //    set { complete = value; }
        //}
        private bool bgf;			/* Battleground flag, internal use */

        public bool Bgf
        {
            get { return bgf; }
            set { bgf = value; }
        }

        private Dictionary<string, int> queststages = new Dictionary<string, int>(); // Hashed by quest name, stage #

        public Dictionary<string, int> Queststages
        {
            get { return queststages; }
            set { queststages = value; }
        }
        private string script_flags = "";	/* Actual new script language flags. */

        public string Script_flags
        {
            get { return script_flags; }
            set { script_flags = value; }
        }
        private string email = "";	/* Email address */

        public string Email
        {
            get { return email; }
            set { email = value; }
        }
        private int questflag = 0;		/* Questflag, internal use */

        public int Questflag
        {
            get { return questflag; }
            set { questflag = value; }
        }
        private int tps = 0;			/* Travel points */

        public int Tps
        {
            get { return tps; }
            set { tps = value; }
        }
        private int nRemortTimes = 0;		/* Remort times.. */

        public int NRemortTimes
        {
            get { return nRemortTimes; }
            set { nRemortTimes = value; }
        }
        private int tickcounts = 0;		/* Spell delay, internal use */

        public int Tickcounts
        {
            get { return tickcounts; }
            set { tickcounts = value; }
        }
        private int warpoints = 0;	/* War points */

        public int Warpoints
        {
            get { return warpoints; }
            set { warpoints = value; }
        }
        private bool challenge_on = false;		/* Arena challenges on/off? */

        public bool Challenge_on
        {
            get { return challenge_on; }
            set { challenge_on = value; }
        }
        private int arena_msg = 0;		/* Arena message status */

        public int Arena_msg
        {
            get { return arena_msg; }
            set { arena_msg = value; }
        }
        private bool challenged = false;		/* Has been challenged? */

        public bool Challenged
        {
            get { return challenged; }
            set { challenged = value; }
        }
        private string challenged_by = string.Empty;	/* Challenged by whom? */

        public string Challenged_by
        {
            get { return challenged_by; }
            set { challenged_by = value; }
        }
        private int challenge_time = 0;	/* Challenge time counter */

        public int Challenge_time
        {
            get { return challenge_time; }
            set { challenge_time = value; }
        }
        private string temp = "";		/* Temp string for delay command use */

        public string Temp
        {
            get { return temp; }
            set { temp = value; }
        }
        private int number_pets = 0;		/* Number of current pets */

        public int Number_pets
        {
            get { return number_pets; }
            set { number_pets = value; }
        }
        private int pagelen = 25;		/* Physical page length */

        public int Pagelen
        {
            get { return pagelen; }
            set { pagelen = value; }
        }
        // TODO: Unknown if this will be used:
        // public int raceflag;		/* Race flag for current race */
        private GuildType guilds;			/* Guild flags */

        public GuildType Guilds
        {
            get { return guilds; }
            set { guilds = value; }
        }
        private int warned = 0;		/* Warned, for old style JAIL */

        public int Warned
        {
            get { return warned; }
            set { warned = value; }
        }
        private int jail_served = 0;		/* RoomVnumForJail hours served. */

        public int Jail_served
        {
            get { return jail_served; }
            set { jail_served = value; }
        }
        private int no_quit = 0;		/* No_quit mobSelfDestructsAt values */

        public int No_quit
        {
            get { return no_quit; }
            set { no_quit = value; }
        }
        private int no_quit_pk = 0;		/* No_quit mobSelfDestructsAt values for PK fight */

        public int No_quit_pk
        {
            get { return no_quit_pk; }
            set { no_quit_pk = value; }
        }
        private List<string> trophy_names = new List<string>();

        public List<string> Trophy_names
        {
            get { return trophy_names; }
            set { trophy_names = value; }
        }
        private List<int> trophy_times = new List<int>();

        public List<int> Trophy_times
        {
            get { return trophy_times; }
            set { trophy_times = value; }
        }
        private List<int> trophy_level = new List<int>(); /* MinimumLevelToViewTopic at which you last pk'd them */

        public List<int> Trophy_level
        {
            get { return trophy_level; }
            set { trophy_level = value; }
        }
        private IStats PermanentStats = new Stats();

        public IStats PermanentStats1
        {
            get { return PermanentStats; }
            set { PermanentStats = value; }
        }
        private IStats TemporaryStats = new Stats();

        public IStats TemporaryStats1
        {
            get { return TemporaryStats; }
            set { TemporaryStats = value; }
        }
        private IStats Modifiers = new Stats();

        public IStats Modifiers1
        {
            get { return Modifiers; }
            set { Modifiers = value; }
        }
        private int[] condition = new int[10];		/* Drunk,Thirsty,Hungry stats */

        public int[] Condition
        {
            get { return condition; }
            set { condition = value; }
        }
        public ThreadSafeLookupNonRef<int, int> learned = new ThreadSafeLookupNonRef<int, int>();	/* Learned level for skills and spells */

        public ThreadSafeLookupNonRef<int, int> Learned
        {
            get { return learned; }
            set { learned = value; }
        }
        private long bank = 0;		/* Money in the bank, in copper */

        public long Bank
        {
            get { return bank; }
            set { bank = value; }
        }
        private int totalkills = 0;		/* Total kills */

        public int Totalkills
        {
            get { return totalkills; }
            set { totalkills = value; }
        }
        private int killpoints = 0;		/* Kill points */

        public int Killpoints
        {
            get { return killpoints; }
            set { killpoints = value; }
        }
        private int deaths = 0;			/* Times the player has died */

        public int Deaths
        {
            get { return deaths; }
            set { deaths = value; }
        }
        private int no_spam = 0;	/* NOspam setting */

        public int No_spam
        {
            get { return no_spam; }
            set { no_spam = value; }
        }
        private int quiet = 0;		/* In quite mode/busy mode/normal mode */

        public int Quiet
        {
            get { return quiet; }
            set { quiet = value; }
        }
        private bool show_lev = false;		/* Show level in 'who' list? */

        public bool Show_lev
        {
            get { return show_lev; }
            set { show_lev = value; }
        }
        private bool just_investigated = false;	/* Just investigated a corpse recently? */

        public bool Just_investigated
        {
            get { return just_investigated; }
            set { just_investigated = value; }
        }
        private List<string> aliasname = new List<string>();	/* Alias names */

        public List<string> Aliasname
        {
            get { return aliasname; }
            set { aliasname = value; }
        }
        private List<string> alias = new List<string>();	/* Alias expansion */

        public List<string> Alias
        {
            get { return alias; }
            set { alias = value; }
        }

        /* Additions */
        private Implants implants_1;		/* Implants for aliens */

        public Implants Implants_1
        {
            get { return implants_1; }
            set { implants_1 = value; }
        }
        // TODO: NO CLUE
        private int implants_2;		/* Implants for aliens */

        public int Implants_2
        {
            get { return implants_2; }
            set { implants_2 = value; }
        }
        private string short_descr;		/* Short description of player */

        public string Short_descr
        {
            get { return short_descr; }
            set { short_descr = value; }
        }
        private string long_descr = "";		/* Long description of player */

        public string Long_descr
        {
            get { return long_descr; }
            set { long_descr = value; }
        }
        private string description = "";		/* Textual description of player */

        public string Description
        {
            get { return description; }
            set { description = value; }
        }
        private int alignment = 0;		/* Player's alignment */

        public int Alignment
        {
            get { return alignment; }
            set { alignment = value; }
        }

        private long effects1 = (long)EffectType.NONE;

        public long Effects1
        {
            get { return effects1; }
            set { effects1 = value; }
        }

        private PlayerSettings settings;

        public PlayerSettings Settings
        {
            get { return settings; }
            set { settings = value; }
        }
        private int level = 0;		/* Player's level */

        public int Level
        {
            get { return level; }
            set { level = value; }
        }
        private double carry_weight = 0;		/* Player's current carryingObjects weight */

        public double Carry_weight
        {
            get { return carry_weight; }
            set { carry_weight = value; }
        }
        private int carry_number = 0;		/* Carrying this amount of items */

        public int Carry_number
        {
            get { return carry_number; }
            set { carry_number = value; }
        }
        private Sex sex = Sex.NEUTRAL;			/* Male/female */

        public Sex PSex
        {
            get { return sex; }
            set { sex = value; }
        }
#if NO_SILVERLIGHT
        [NonSerialized]
#endif
        public string racename = string.Empty;			/* Player race this character is */

        public string Racename
        {
            get { return racename; }
            set { racename = value; }
        }
        private Queue<string> last_tells = new Queue<string>();	/* Circular list of last tells */

        public Queue<string> Last_tells
        {
            get { return last_tells; }
            set { last_tells = value; }
        }
        private int temp_room = 0;	/* Temporary currentRoom, internal use */

        public int Temp_room
        {
            get { return temp_room; }
            set { temp_room = value; }
        }

        #region "Properties"
        public bool IsEvil
        {
            get
            {
                return (alignment < -150) ? true : false;
            }
        }

        public bool IsGood
        {
            get
            {
                return (alignment > 150) ? true : false;
            }
        }

        public bool IsNeutral
        {
            get
            {
                return !(IsEvil || IsGood);
            }
        }
        #endregion

        public bool this[Implants implant] { get { return (implants_1 & implant) != 0; } }
        public bool HasSpecialBits(PlayerSpecialBits special) { return (specialbits & special) != 0; }
        public bool SettingIsOn(PlayerSettings setting) { return (settings & setting) != 0; }
        public void EnforceRaceStatLimit()
        {
            RaceData race = (RaceData)GetRaceData();
            if (race != null)
            {
                EnforceRaceStatLimit(race);
            }
        }

        public void EnforceRaceStatLimit(RaceData race)
        {
            if (race != null)
            {
                for (int i = 0; i < (int)StatTypes.MaxStatNumber; i++)
                {
                    if (((Stats)PermanentStats)[i] > race.Limits[i])
                        ((Stats)PermanentStats)[i] = race.Limits[i];
                }
            }
        }

        public RaceData GetRaceData()
        {
            return RaceData.GetRaceData(racename);
        }


    }
}
